package com.sugo.seckill.web.order;

import com.sugo.seckill.error.BaseException;
import com.sugo.seckill.http.HttpResult;
import com.sugo.seckill.http.HttpStatus;
import com.sugo.seckill.mq.MqProducer;
import com.sugo.seckill.order.service.SeckillOrderService;
import com.sugo.seckill.pojo.FrontUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.*;


/**
 * controller
 * @author Administrator
 *
 */
@RestController
@RequestMapping("/seckill")
public class SeckillOrderController {

	@Autowired
	private SeckillOrderService seckillOrderService;


			/**
             * @Description: 获取时间
             * @Author: hubin
             * @CreateDate: 2020/6/10 16:19
             * @UpdateUser: hubin
             * @UpdateDate: 2020/6/10 16:19
             * @UpdateRemark: 修改内容
             * @Version: 1.0
             */
	@RequestMapping("/submitOrder/times")
	public HttpResult getConcurrentTime(){
		return HttpResult.ok(System.currentTimeMillis()+"");
	}


	@RequestMapping("/test")
	public HttpResult getSeckillGoods(Long seckillId){
		seckillOrderService.getSeckillGoods(seckillId);
		return HttpResult.ok();
	}

	/**
	 * @Description: 普通下单操作
	 * @Author: hubin
	 * @CreateDate: 2020/11/27 22:01
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/11/27 22:01
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@RequestMapping("/order/kill/{killId}/{token}")
	public HttpResult startKilled(@PathVariable Long killId, @PathVariable String token){
		//判断
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_EXPECTATION_FAILED,"用户未登录");
		}
		//获取用户数据
		FrontUser user = seckillOrderService.getUserInfoFromRedis(token);

		//判断
		if(user == null){
			return HttpResult.error(HttpStatus.SC_EXPECTATION_FAILED,"用户未登录");
		}

		//获取userid
		String userId = user.getId()+"";
		//下单
		HttpResult result = seckillOrderService.startKilled(killId, userId);

		return result;

	}


	/**
	 * @Description: 分布式锁下单，MySQL悲观锁的方式
	 * @Author: hubin
	 * @CreateDate: 2020/11/27 22:01
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/11/27 22:01
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@RequestMapping("/order/kill/sql/{killId}/{token}")
	public HttpResult startKilledWithMysqlLock(@PathVariable Long killId, @PathVariable String token){
		//判断
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_EXPECTATION_FAILED,"用户未登录");
		}
		//获取用户数据
		FrontUser user = seckillOrderService.getUserInfoFromRedis(token);

		//判断
		if(user == null){
			return HttpResult.error(HttpStatus.SC_EXPECTATION_FAILED,"用户未登录");
		}

		//获取userid
		String userId = user.getId()+"";
		//下单
		//HttpResult result = seckillOrderService.startKilledWithMysqlLock(killId,userId);

		return null;

	}


	/**
	 * @Description: 分布式锁下单，MySQL悲观锁的方式
	 * @Author: hubin
	 * @CreateDate: 2020/11/27 22:01
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/11/27 22:01
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@RequestMapping("/order/kill/version/{killId}/{token}")
	public HttpResult startKilledWithMysqlVersion(@PathVariable Long killId, @PathVariable String token){
		//判断
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_EXPECTATION_FAILED,"用户未登录");
		}
		//获取用户数据
		FrontUser user = seckillOrderService.getUserInfoFromRedis(token);

		//判断
		if(user == null){
			return HttpResult.error(HttpStatus.SC_EXPECTATION_FAILED,"用户未登录");
		}

		//获取userid
		String userId = user.getId()+"";
		//下单
		//HttpResult result = seckillOrderService.startKilledWithMysqlVersion(killId,userId);

		return null;

	}


	/**
	 * @Description: 分布式锁下单，Redsi方式
	 * @Author: hubin
	 * @CreateDate: 2020/11/27 22:01
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/11/27 22:01
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@RequestMapping("/order/kill/redis/{killId}/{token}")
	public HttpResult startKilledWithRedisLock(@PathVariable Long killId, @PathVariable String token){
		//判断
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_EXPECTATION_FAILED,"用户未登录");
		}
		//获取用户数据
		FrontUser user = seckillOrderService.getUserInfoFromRedis(token);

		//判断
		if(user == null){
			return HttpResult.error(HttpStatus.SC_EXPECTATION_FAILED,"用户未登录");
		}

		//获取userid
		String userId = user.getId()+"";
		//下单
		//HttpResult result = seckillOrderService.startKilledWithRedisLock(killId,userId);

		return null;

	}


	// 创建一个线程池，流量泄洪
	private ExecutorService executorService = new ThreadPoolExecutor(4,
			20,
			100,
			TimeUnit.SECONDS,
			new ArrayBlockingQueue<Runnable>(2000));


	@Autowired
	private MqProducer producer;

			/**
             * @Description: 分布式锁下单，Redsi方式
             * @Author: hubin
             * @CreateDate: 2020/11/27 22:01
             * @UpdateUser: hubin
             * @UpdateDate: 2020/11/27 22:01
             * @UpdateRemark: 修改内容
             * @Version: 1.0
             */
	@RequestMapping("/order/kill/cache/{killId}/{token}")
	public HttpResult startKilledWithCache(@PathVariable Long killId, @PathVariable String token) throws BaseException{
		//判断
		if(StringUtils.isBlank(token)){
			return HttpResult.error(HttpStatus.SC_EXPECTATION_FAILED,"用户未登录");
		}
		//获取用户数据
		FrontUser user = seckillOrderService.getUserInfoFromRedis(token);

		//判断
		if(user == null){
			return HttpResult.error(HttpStatus.SC_EXPECTATION_FAILED,"用户未登录");
		}

		//获取userid
		String userId = user.getId()+"";

		// 发送消息
		// 线程同步方法，20个等待队列，流量泄洪
		Future<Object> future = executorService.submit(new Callable<Object>() {
			// 判断消息发送成功，还是失败
			@Override
			public Object call() throws Exception {

				// 发送消息
				boolean res = producer.asncSendTransactionMsg(killId, userId);

				if(!res){
					// 消息发送失败
					throw new BaseException(HttpStatus.SEC_GOODS_STOCK_FAIL,"消息发送失败");
				}

				return null;
			}
		});

		try {
			future.get();
		} catch (InterruptedException e) {
			e.printStackTrace();
			throw new BaseException(HttpStatus.SEC_GOODS_STOCK_FAIL,"消息发送失败");
		} catch (ExecutionException e) {
			e.printStackTrace();
			throw new BaseException(HttpStatus.SEC_GOODS_STOCK_FAIL,"消息发送失败");
		}

		return HttpResult.ok("下单成功");

	}



}
